<template>
  <view
    class="task-switch"
    id="taskSwitch"
  >
    <view
      v-for="item in data"
      :key="item.value"
      :id="cacheItemId(item.value)"
      :class="currentVal === item.value ? 'active' : ''"
      @click="handleSwitch(item.value)"
    >
      {{ item.label }}
    </view>
    <view ref="switcher" />
  </view>
</template>

<script setup lang="ts">
import { useSelectElement } from '@/hook'
import type { TaskSwitchList, TaskSwitchVal } from './types'

interface Props {
  data: TaskSwitchList[]
  current?: TaskSwitchVal
}
const props = defineProps<Props>()

const $emit = defineEmits(['switch', 'update:current'])

const currentVal = ref<TaskSwitchVal>('')

const itemKeyMap = new Map()
const cacheItemId = (key: TaskSwitchVal): string => {
  const id = `switch-${key}`
  itemKeyMap.set(key, id)
  return id
}

let switchOffsetLeft = 0
/**
 * 获取整个switch的偏移值
 */
const setSwitchOffsetLeft = () => {
  useSelectElement('#taskSwitch', result => {
    if (!Array.isArray(result) && result)
      switchOffsetLeft = result.left as number
  })
}

const switcher = ref<AnyObject>()
/**
 * 根据当前激活的switch子项修改switcher的偏移量
 * @param id 当前激活的switch子项id
 */
const changeSwitcherPosition = (id: TaskSwitchVal) => {
  useSelectElement(`#${itemKeyMap.get(id)}`, result => {
    if (!Array.isArray(result) && result) {
      switcher.value!.$el.style.width = `${result.width}px`
      switcher.value!.$el.style.left = `${
        (result.left as number) - switchOffsetLeft
      }px`
    }
  })
}
/**
 * 当窗口大小发生变化时重新计算偏移量
 */
const onWindowListener = () => {
  setSwitchOffsetLeft()
  changeSwitcherPosition(currentVal.value)
}
onMounted(() => {
  currentVal.value = props.current ?? props.data[0].value
  setSwitchOffsetLeft()
  changeSwitcherPosition(currentVal.value)
  uni.onWindowResize(onWindowListener)
})
onBeforeUnmount(() => {
  uni.offWindowResize(onWindowListener)
})

const handleSwitch = (id: TaskSwitchVal) => {
  if (currentVal.value === id) return
  currentVal.value = id
  $emit('update:current', currentVal.value)
  $emit('switch', currentVal.value)
}
watch(currentVal, () => {
  changeSwitcherPosition(currentVal.value)
})
/**
 * 当传入current值时赋值到currentVal中并计算偏移量，同时监听切换时的偏移量
 */
watch(
  () => props.current,
  nv => {
    currentVal.value = nv as TaskSwitchVal
  }
)
watch(
  () => props.data,
  () => {
    const { current } = props
    changeSwitcherPosition(current ?? currentVal.value)
  },
  { deep: true }
)
</script>

<style lang="scss" scoped>
$task-switch-height: 40px;
$task-switch-bg-color: #346ab1;

.task-switch {
  height: $task-switch-height;
  line-height: $task-switch-height;
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  text-align: center;
  background-color: $task-switch-bg-color;
  color: #ffffff;
  font-size: 28rpx;
  font-weight: bolder;
  border-radius: 50rpx;
  & > view {
    height: 100%;
    line-height: inherit;
    flex: auto;
    cursor: pointer;
  }
  & > view:last-of-type {
    position: absolute;
    top: 0;
    z-index: -1;
    background-color: #ffffff;
    border-radius: 50rpx;
    transition: all 0.3s ease;
    pointer-events: none;
  }
}

.active {
  color: #346ab1;
}
</style>
